package com.springcloud.sc.ucpv5.client.application.message.connect;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.SocketException;


import com.springcloud.sc.ucpv5.client.application.message.MessageService;
import com.springcloud.sc.ucpv5.client.application.message.type.shortType.UnShort_Wrap;
import com.springcloud.sc.ucpv5.client.application.util.Constant;
import com.springcloud.sc.ucpv5.client.common.CmdDefine;
import com.springcloud.sc.ucpv5.client.commondata.data.HertHandleMsg;
import com.springcloud.sc.ucpv5.client.commondata.data.MsgHeader;
import com.springcloud.sc.ucpv5.client.module.datamanager.BaseDataManager;
import com.springcloud.sc.ucpv5.client.util.CorbarUtil;
import com.springcloud.sc.ucpv5.client.util.DateToolUtil;
import com.sun.jna.Native;
import com.sun.jna.win32.StdCallLibrary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.net.ConnectionResetException;

public class VtcpConnect extends ConnectFather {
	private static final Logger logger = LoggerFactory.getLogger(TcpProBufConnect.class);
    private static ShakeHandThread shakeHandThread = new ShakeHandThread();

    public static interface Vtcp_dll extends StdCallLibrary {
	// 这句是利用Native.loadLibrary加载所要访问的动态链接库
	static Vtcp_dll INSTANCE = (Vtcp_dll) Native.loadLibrary("dvtcp", Vtcp_dll.class);

	int dvtcp_socket();

	int dvtcp_connect(int fd, String ip, int port);

	int dvtcp_send(int fd, byte[] buffer, int cb);

	// int dvtcp_sendto(int fd, String buffer, int cb, String ip, int port);
	int dvtcp_recv(int fd, byte[] buffer, int cb);

	// int dvtcp_recvfrom(int fd, String buffer, int cb, struct sockaddr*
	// from);
	int dvtcp_close(int fd);
    }

    private int connectSocket = -1;

    public int internalInit(String strServerIP, int iServerPort, boolean isReconnect) {
	try {
	    try {
		logger.info("VtcpConnect internalInit  1 connectSocket : " + connectSocket);
		if (connectSocket > -1) {
		    VtcpConnect.Vtcp_dll.INSTANCE.dvtcp_close(connectSocket);
		    connectSocket = -1;
		}

		logger.info("VtcpConnect internalInit  2 connectSocket : " + connectSocket);

		connectSocket = VtcpConnect.Vtcp_dll.INSTANCE.dvtcp_socket();

		logger.info("VtcpConnect internalInit  3 connectSocket : " + connectSocket);

		if (connectSocket > -1) {

		    logger.info("VtcpConnect internalInit  4 connectSocket : " + connectSocket);

		    int value = VtcpConnect.Vtcp_dll.INSTANCE.dvtcp_connect(connectSocket, strServerIP, 9778);

		    logger.info("VtcpConnect internalInit  5 value : " + value);

		    if (value < 0) {
			return ERROR_CODE_CONNECT_FAIL;
		    }
		}
	    } catch (Exception e) {
		logger.info("VtcpConnect internalInit Excetipin 1:" + e.getMessage(), e);
		return ERROR_CODE_CONNECT_FAIL;
	    }

	    // 消息接受流程
	    startReadThread();

	    shakeHandThread.setShakeHandTime(0);

	    return 0;
	    // return tmpresult.getRetCode();
	} catch (Exception ex) {
	    logger.info("VtcpConnect internalInit Excetipin 2:" + ex.getMessage(), ex);
	    return ERROR_CODE_CONNECT_FAIL;
	}
    }

    public int writeByteMsg(byte[] content) {
	if (!checkConnectOk()) {
	    return ERROR_CODE_SOCKET_SHUTDOWN;
	}
	ByteArrayOutputStream outStream = new ByteArrayOutputStream();
	try {

	    outStream.write(SOCKET_MSG_BEGIN);
	    // 写消息长度
	    outStream.write(UnShort_Wrap.packUnShort((short) (content.length + SOCKET_MSG_LENGTH), SOCKET_MSG_LENGTH, false));
	    // 写消息内容
	    outStream.write(content);

	    outStream.write(SOCKET_MSG_END);

	    byte[] sendContent = outStream.toByteArray();

	    int returnVaule = VtcpConnect.Vtcp_dll.INSTANCE.dvtcp_send(connectSocket, sendContent, sendContent.length);
	    if (returnVaule > 0) {
		return 0;
	    } else {
		return ERROR_CODE_WRITE_SOCKET_FAIL;
	    }
	} catch (ConnectionResetException exp) {
	    // exp.printStackTrace();
	    return ERROR_CODE_SOCKET_SHUTDOWN;
	} catch (SocketException exp) {
	    return ERROR_CODE_SOCKET_SHUTDOWN;
	} catch (Throwable exp) {
	    // exp.printStackTrace();
	    return ERROR_CODE_WRITE_SOCKET_FAIL;
	} finally {
	    try {
		outStream.close();
	    } catch (IOException e) {
		// e.printStackTrace();
	    }
	}
    }

    public void close() {
	try {
	    super.close();
	    if (checkConnectOk()) {
		logger.info("VtcpConnect close 链接关闭调用 !");
		VtcpConnect.Vtcp_dll.INSTANCE.dvtcp_close(connectSocket);
		connectSocket = -1;
	    }
	    try {
		shakeHandThread.stop();
	    } catch (Exception e) {
		// TODO: handle exception
	    }
	} catch (Exception e) {
	    // TODO: handle exception
	}
    }

    public boolean checkConnectOk() {
	// TODO Auto-generated method stub
	if (connectSocket > -1) {
	    return true;
	} else {
	    return false;
	}
    }

    public void setConnnectClose() {
	// TODO Auto-generated method stub
	close();
    }

    public boolean isLocalPortRight() {
	// TODO Auto-generated method stub
	return true;
    }

    public byte[] readSocket(int len) {
	// System.out.println("readSocket 1:" + len);
	if (!checkConnectOk()) {
	    return null;
	}
	// System.out.println("readSocket 2:" + len);
	ByteArrayOutputStream outStream = new ByteArrayOutputStream();
	try {
	    while (outStream.size() < len && checkConnectOk()) {
		byte[] buf = new byte[len - outStream.size()];

		int rendLen = VtcpConnect.Vtcp_dll.INSTANCE.dvtcp_recv(connectSocket, buf, len - outStream.size());
		if (rendLen > 0) {
		    outStream.write(buf, 0, rendLen);
		} else if (rendLen == 0) {
		    try {
			Thread.sleep(10);
		    } catch (Exception e) {
			// TODO: handle exception
		    }
		} else {
		    return null;
		}
	    }
	} catch (Exception e) {
	    e.printStackTrace();
	}
	byte[] returnValue = outStream.toByteArray();

	return returnValue;
    }

    public void doDataToServer(MessageData messageData) {
	try {
	    com.springcloud.sc.ucpv5.client.commondata.idl.sj3.MsgHeader msgHeader = (com.springcloud.sc.ucpv5.client.commondata.idl.sj3.MsgHeader) messageData.header.dataChangeCommonToCorbarData();
	    try {
		if (messageData.header.SessionID != getSessionId()) {
		    // 非当前登录需要的登录消息, 丢弃
		    // return;
		}

		com.google.protobuf.Message value = messageData.message.dataChangeCommonToProBufData();
		org.omg.CORBA.portable.Streamable holder = messageData.message.dataChangeCommonToCorbarDataHolder();
		msgHeader.MsgContent = CorbarUtil.struct2Byte(holder);

			com.springcloud.sc.ucpv5.client.commondata.idl.sj3.MsgHeaderHolder headHolder = new com.springcloud.sc.ucpv5.client.commondata.idl.sj3.MsgHeaderHolder();
		headHolder.value = msgHeader;

		// 后台发送
//		if (msgHeader.CmdID == Constant.CMD_COMMUNICATION_SHAKEHAND) {
//		    logger.info("!!!!!!!!!!!前台发送握手信息 " + DateToolUtil.getCurTime());
//		}

		writeByteMsg(CorbarUtil.struct2Byte(headHolder));
	    } catch (Exception e) {
		e.printStackTrace();
	    }
	} catch (Exception e) {
	    // TODO: handle exception
	}
    }

    public void doDataFromServer(Object msg) {
	try {
	    byte[] content = (byte[]) msg;
	    MsgHeader header = new MsgHeader();
	    header.dataContentDataToCommon(content);

//	    if (header.CmdID == Constant.CMD_COMMUNICATION_SHAKEHAND) {
//		logger.info("!!!!!!!!!!!前台收到握手信息 " + DateToolUtil.getCurTime());
//	    }

	    // logger.info("收到回应包:" + header.CmdID);
	    // wsy 20180725 如果上报消息的节点在服务器无法找到, 则丢弃
	    if (header.CmdID != CmdDefine.CMD_User_Login && header.CmdID != CmdDefine.CMD_User_Login_regcheck && header.CmdID != CmdDefine.CMD_User_Login_md5
		    && header.CmdID != CmdDefine.CMD_User_Login_md5_check) {
		if (BaseDataManager.getInstance().nodeGet(header.NodeNumber) == null) {
		    return;
		}
	    }

	    if (header.CmdID == CmdDefine.CMD_User_Logout) { // 如果登录消息响应用的话，把相关信息记录起来
		// 记录握手成功时间
		shakeHandThread.setShakeHandTime(0);
		shakeHandThread.stop();
		return;

	    } else if (header.CmdID == Constant.CMD_COMMUNICATION_SHAKEHAND) {
		try {
		    HertHandleMsg holder = new HertHandleMsg();
		    holder.dataContentDataToCommon(header.MsgContent);
		    //logger.info("!!!!!!!!!!!收到握手消息返回  结果:" + holder.reason + " " + DateToolUtil.getCurTime());

		    // if (holder != null && holder.reason == 1) {
		    // shakeHandThread.shakeHand(2);
		    // shakeHandThread.setShakeHandTime(System.currentTimeMillis());
		    // }
		    shakeHandThread.shakeHand(2);
		    shakeHandThread.setShakeHandTime(System.currentTimeMillis());
		    // TODO 握手消息处理
		} catch (Throwable e) {
		    e.printStackTrace();
		    logger.info("!!!!!!!!!!!收到握手消息返回 异常:" + DateToolUtil.getCurTime(), e);
		}

		return;
	    }
	    MessageService.getInstance().putMessage(header);

	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    /**
     * 启动握手, 在系统登录成功后启动
     */
    public void checkShakeHand() {
	try {
	    // 记录握手成功时间
	    shakeHandThread.setShakeHandTime(0);
	    shakeHandThread.beginShakeHands();
	} catch (Exception e) {
	    // TODO: handle exception
	}
    }
}
